package com.idea.relax.log.support;

import org.springframework.boot.autoconfigure.condition.ConditionOutcome;
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.context.annotation.Conditional;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;
import org.springframework.util.ClassUtils;

import java.lang.annotation.*;
import java.util.Map;
import java.util.Objects;

/**
 * @author: 沉香
 * @date: 2023/1/30
 * @description:
 */
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(ConditionalMultiple.ConditionalMultipleCondition.class)
public @interface ConditionalMultiple {

    String[] classNames();

    String[] attributes();

    String[] havingValues();

    class ConditionalMultipleCondition extends SpringBootCondition {

        @Override
        public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {

            Environment environment = context.getEnvironment();
            Map<String, Object> attrMap = metadata.getAnnotationAttributes(ConditionalMultiple.class.getName());
            String[] attributes = (String[]) Objects.requireNonNull(attrMap).get("attributes");
            String[] havingValues = (String[]) Objects.requireNonNull(attrMap).get("havingValues");
            if (havingValues.length == 0 || attributes.length == 0){
                throw new IllegalStateException();
            }
            boolean isOne = false;
            String havingValue = "";
            if (havingValues.length == 1){
                havingValue = havingValues[0];
                isOne = true;
            }
            for (int i = 0; i < attributes.length; i++) {
                String property = environment.getProperty(attributes[i]);
                if (isOne && !havingValue.equals(property) ||
                        !havingValues[i].equals(property)) {
                    return ConditionOutcome.noMatch("");
                }

            }
            ClassLoader classLoader = context.getClassLoader();
            String[] classNames = (String[]) Objects.requireNonNull(attrMap).get("classNames");
            for (int i = 0; i < classNames.length; i++) {
                if (!ClassUtils.isPresent(classNames[i], classLoader)) {
                    return ConditionOutcome.noMatch("");
                }
            }
            return ConditionOutcome.match();
        }
    }


}
